import {d3_cube} from "@/views/cg/lib/shape";
import {Mat4, multiply4, multiply3} from "@/views/cg/lib/matrix";
import {d3_cylinder, d3_shpere_texture} from '@/views/cg/lib/shape';
import RenderContext from "@/views/cg/lib/RenderContext.ts";
import {Model} from "@/views/cg/lib";

// 概念节点
export default class Robot extends Model{
 constructor() {
   super(null);

   this.head = new Head()
   this.body = new Body()
   this.leftArm = new Arm({
     isLeft: true,
     length:0.5,
     size:0.1,
     x:-0.45,
     y:0.22,
     ax:0,
     az:-Math.PI*0.2
   })

   this.rightArm = new Arm({
     isLeft: false,
     length:0.5,
     size:0.1,
     x:0.45,
     y:0.22,
     ax:0,
     az:Math.PI*0.2
   })

   this.leftLeg = new Leg({
     isLeft: true,
     length:0.8,
     size:0.15,
     x:-0.2,
     y:-0.5,
     ax:0,
     az:-Math.PI*0.1
   })

   this.rightLeg = new Leg({
     isLeft: false,
     length:0.8,
     size:0.15,
     x:0.2,
     y:-0.5,
     ax:0,
     az:-Math.PI*0.1
   })

   this.addChild(this.body)
   this.addChild(this.head)
   this.addChild(this.leftArm)
   this.addChild(this.rightArm)
   this.addChild(this.leftLeg)
   this.addChild(this.rightLeg)

   this.walk()
 }

 walk(){
   // 實現全局統一守時
   const timing = RenderContext.getTiming()
    // A 控制速度 越小越快
   let A = 200
   let MaxAngle = Math.PI * 0.25
   timing.listen(({diff}) => {
     // 产生挥手动画
     const stage = Math.floor(diff/A) % 4
     let ax = null

     // 分段 stage 如果是 0 往前走  1、2  3
     // 0 -> | [0, A]
     // 1 <-, 2 <- [A,-A]
     // 3->[-A,0]

     switch (stage){
       case 0:{
         const t = diff % A
         ax = (t/A) * MaxAngle
         break
       }

       case 1:
       case 2:{
         // diff -A 过了A的时间
         const t = (diff -A ) % (2*A)
         ax = MaxAngle - 2*MaxAngle*(t/(2*A))
         break
       }
       case 3:{
         const t = (diff - 3*A) % A
         ax = -MaxAngle + MaxAngle*(t/A)
         break
       }
     }
     this.head.look(ax * 0.3)
     this.leftArm.rotate(ax, -Math.PI * 0.1)
     this.leftArm.children[0].rotate(ax * 0.1, 0)
     this.rightArm.rotate(-ax, Math.PI*0.1)
     this.rightArm.children[0].rotate(-ax * 0.1, 0)
     this.leftLeg.rotate(-ax, -Math.PI * 0.1)
     this.rightLeg.rotate(ax, Math.PI * 0.1)
   })
 }
}

class Body extends Model{
  constructor() {
    let mesh = d3_cube(false, true)
    super(mesh);

    this.name = 'body'
    const mat4 = new Mat4()
    this.setUnitMatrix(
      mat4.scale(0.3,0.5,0.25)
        .getMatrix()
    )
    this.addTextureImage('/texture02.jpg')
  }
}

class Head extends Model{
  constructor() {
    const mesh = d3_shpere_texture(0.3)
    super();

    this.name = 'head'
    const mat4 = new Mat4()
    this.setUnitMatrix(
      mat4.translate(0,0.8,0)
        .rotate(0, Math.PI/2,0)
        .getMatrix()
    )

    this.addTextureImage('/texture01.jpg')
  }

  look(ax){
    const mat4 = new Mat4()
    this.setUnitMatrix(
      mat4.translate(0,0.8,0)
        .rotate(0, Math.PI/2+ax, 0)
        .getMatrix()
    )
  }
}

class Arm extends Model{
  constructor({
    isLeft, length,
    size, x, y, ax, az,
    level = 0
  }) {
    // ax az xz转动的角度
    // 圆柱体mesh
    const mesh = d3_cylinder(size, length)
    super(mesh);

    const mat4 = new Mat4()
    // 深度
    this.level = level
    this.x = x
    this.y = y
    this.length = length

    this.setUnitMatrix(this.__matrix(ax,az))
    this.addTextureImage("/texture03.jpg")

    // 下一级的机械臂有个弯曲
    if(this.level !== 1){
      const sign = isLeft?1:-1;
      this.addChild(new Arm({
        isLeft:true,
        x:0,
        y:-length,
        ax:0,
        az:size*0.3,
        length:length,
        size:0.08,
        level: this.level+ 1
      }))
    }
  }

  __matrix(ax,az){
    const mat4 = new Mat4()
    return mat4
      // 旋转点不在原点
      .translate(0, -this.length/2,0)
      .rotate(ax,0,az)
      // 旋转点不在原点 要移动回来
      .translate(0, this.length/2, 0)
      // 这个是把机械臂放到肩膀的位置
      .translate(this.x, this.y, 0)
      .getMatrix()
  }

  rotate(ax,az){
    this.setUnitMatrix(this.__matrix(ax,az))
  }
}

// 腿继承自arm
class Leg extends Arm{
  constructor(options) {
    super(options);
  }
}
